package com.example.pagoda;

import java.util.HashMap;
import java.util.Map;

/**
 * Enigma 加密程序
 * 转子初始偏移位置
 * int dA=-20,dB=-25,dC=-16; 分别代表，慢转子偏移 20个位置，中转子偏移25个位置，快转子偏移16个位置
 * Created by tangz on 2019/10/2.
 */
public class Encryption {

    public static void main(String[] args) {
        //0位置补0，从1开始【因为转的第一列数字都是有序的，所以只需要用三个数组。转子旋转，不需要把数组元素挨个位移（时间复杂度x26n）。只需要用一个标记变量实现】
        int rotorA[] = new int[]{0, 1, 19, 10, 14, 26, 20, 8, 16, 7, 22, 4, 11, 5, 17, 9, 12, 23, 18, 2, 25, 6, 24, 13, 21, 3, 15};
        int rotorB[] = new int[]{0, 1, 6, 4, 15, 3, 14, 12, 23, 5, 16, 2, 22, 19, 11, 18, 25, 24, 13, 7, 10, 8, 21, 9, 26, 17, 20};
        int rotorC[] = new int[]{0, 8, 18, 26, 17, 20, 22, 10, 3, 13, 11, 4, 23, 5, 24, 9, 12, 25, 16, 19, 6, 15, 21, 2, 7, 1, 14};
        Map<Integer, Integer> rotorAMap = new HashMap<Integer, Integer>();
        Map<Integer, Integer> rotorBMap = new HashMap<Integer, Integer>();
        Map<Integer, Integer> rotorCMap = new HashMap<Integer, Integer>();
        for (int i = 1; i <= 26; i++) {
            rotorAMap.put(rotorA[i], i);
            rotorBMap.put(rotorB[i], i);
            rotorCMap.put(rotorC[i], i);
        }
        //计算转子的内部字母对的偏移大小
        int deviationA[] = new int[27];
        int deviationB[] = new int[27];
        int deviationC[] = new int[27];
        for (int i = 1; i <= 26; i++) {
            //System.out.println(deviationA[i]+" "+ i +" "+rotorAMap.get(i));
            int t1 = (rotorAMap.get(i) - i + 26) % 26;
            int t2 = (rotorBMap.get(i) - i + 26) % 26;
            int t3 = (rotorCMap.get(i) - i + 26) % 26;
            deviationA[i] = t1 == 0 ? 26 : t1;
            deviationB[i] = t2 == 0 ? 26 : t2;
            deviationC[i] = t3 == 0 ? 26 : t3;
        }
        //明文
        String plainstr = "PAGODAWILLBEBETTER";
        char plainChars[] = plainstr.toCharArray();
        int plainText[] = new int[18];
        for (int i = 0; i < plainChars.length; i++) {
            plainText[i] = plainChars[i] - 'A' + 1;
        }
        //转子初始偏移位置
        int dA = -20, dB = -25, dC = -16;
        //字母A对应转子初始位置 对应顺序下标位置
        int cA, cB, cC;
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < plainText.length; i++) {
            cA = plainText[i];
            int t1 = ((cA + dA + 26) % 26);
            t1 = t1 == 0 ? 26 : t1;
            cB = (cA + deviationA[t1]) % 26;
            int t2 = ((cB + dB + 26) % 26);
            t2 = t2 == 0 ? 26 : t2;
            cC = (cB + deviationB[t2]) % 26;
            int t3 = ((cC + dC + 26) % 26);
            t3 = t3 == 0 ? 26 : t3;
            System.out.println("cA = " + cA + " cB = " + cB + " cC = " + cC);
            System.out.println(" deviationA = " + deviationA[t1] + " deviationB = " + deviationB[t2] + " deviationC = " + deviationC[t3]);
            int ciphertext = (plainText[i] + deviationA[t1] + deviationB[t2] + deviationC[t3]) % 26;
            ciphertext = ciphertext == 0 ? 26 : ciphertext;
            System.out.println("ciphertext = " + ciphertext);
            stringBuffer.append((char) (ciphertext + 64));
            //dC 旋转
            dC--;
        }
        System.out.println("result = " + stringBuffer.toString());
    }

}